﻿// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "DesignInterface.h"
#include "Blueprint/UserWidget.h"
#include "StatePattern.generated.h"

/**	状态模式 State Pattern
 *	描述
 *		允许一个对象在其内部状态改变时改变它的行为，对象看起来似乎修改了它的类。
 *		其别名为状态对象(Objects for States)，状态模式是一种对象行为型模式。
 *	有限状态机（FSMs）
 *		拥有状态机所有可能状态的集合
 *		状态机同时只能在一个状态
 *		一连串的输入或事件被发送给状态机
 *		每个状态都有一系列的转移，每个转移与输入和另一状态相关
 *		动画状态机系统、行为树系统来理解
 *	并发状态机
 *		有些状态需要并行执行，例如动画状态机，经常分为上半身动画与下半身动画融合，如装备动作、射击动作、换弹动作与行走动作并行
 *	层次状态机
 *		状态中嵌套子状态，可以使用继承实现或者状态栈来实现
 *	下推自动机
 *		用栈来存储一系列状态。有限状态机有一个指向状态的指针，下推自动机有一栈指针
 *		新状态压入栈中，“当前的”状态总是在栈顶
 *		弹出最上面的状态，这个状态会被销毁，它下面的状态成为新状态。如UI界面管理
 *	套路
 *		环境类 Context，用于改变状态
 *		抽象状态类 State
 *		具体状态类 ConcreteState
 *		使用场景
 *		对象的行为依赖于它的状态（属性）并且可以根据它的状态改变而改变它的相关行为。
 *		代码中包含大量与对象状态有关的条件语句，这些条件语句的出现，会导致代码的可维护性和灵活性变差，不能方便地增加和删除状态，使客户类与类库之间的耦合增强。在这些条件语句中包含了对象的行为，而且这些条件对应于对象的各种状态。
 *	示例
 *		OA办公系统中多种状态：尚未办理；正在办理；正在批示；正在审核
 *		TCP 连接状态
 *		动画系统、AI行为树
 *		UI界面管理
 *	优缺点
 *		优点
 *			封装了转换规则。
 *			枚举可能的状态，在枚举状态之前需要确定状态种类。
 *			将所有与某个状态有关的行为放到一个类中，并且可以方便地增加新的状态，只需要改变对象状态即可改变对象的行为。
 *			允许状态转换逻辑与状态对象合成一体，而不是某一个巨大的条件语句块。
 *			可以让多个环境对象共享一个状态对象，从而减少系统中对象的个数。
 *		缺点
 *			状态模式的使用必然会增加系统类和对象的个数。
 *			状态模式的结构与实现都较为复杂，如果使用不当将导致程序结构和代码的混乱。
 *			状态模式对“开闭原则”的支持并不太好，对于可以切换状态的状态模式，增加新的状态类需要修改那些负责状态转换的源代码，否则无法切换到新增状态；而且修改某个状态类的行为也需修改对应类的源代码。
 **/

UCLASS()
class MISCELLANEOUSPROJECT_API UStateBaseStateWidget : public UUserWidget, public IStateInterface
{
	GENERATED_BODY()
public:
	virtual void EnterState() override;
	virtual void ExitState() override;

	UFUNCTION(BlueprintNativeEvent,BlueprintCallable,Category = "State Pattern")
	void OnEnterState();
	UFUNCTION(BlueprintNativeEvent, BlueprintCallable, Category = "State Pattern")
	void OnExitState();
};

UCLASS()
class MISCELLANEOUSPROJECT_API AStateUIStateManager : public AActor
{
	GENERATED_BODY()
public:
	// 改变状态
	UFUNCTION(BlueprintCallable, Category = "State Pattern")
	void EnterState(TSubclassOf<UStateBaseStateWidget> StateWidgetClass);

	// 退出所有状态
	UFUNCTION(BlueprintCallable, Category = "State Pattern")
	void ExitAllState();

	// 当前状态实例
	UPROPERTY(BlueprintReadWrite, Category = "State Pattern")
	UStateBaseStateWidget* CurrentStateWidget;

private:
	// 存储状态实例
	TMap<TSubclassOf<UStateBaseStateWidget>, UStateBaseStateWidget*> WidgetInstances;
};
